package com.sc.nft.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sc.nft.dao.*;
import com.sc.nft.entity.*;
import com.sc.nft.entity.vo.*;
import com.sc.nft.enums.ExpenditureRecordTypeEnum;
import com.sc.nft.enums.RankingBoardIncomeAndRewardsStatusEnum;
import com.sc.nft.enums.RankingBoardRewardsTypeEnum;
import com.sc.nft.enums.RankingBoardTypeEnum;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.service.UserRankingBoardDetailsService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import com.sc.nft.service.AdminRankingBoardConfService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;

/**
 * 排行榜配置表服务接口实现
 *
 * @author Sun
 * @since 2023-08-03 16:44:17
 * @description 由 Mybatisplus Code Generator 创建
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class AdminRankingBoardConfServiceImpl implements AdminRankingBoardConfService {

    private final RankingBoardConfDao rankingBoardConfDao;
    private final DigitalCollectionDao digitalCollectionDao;
    private final EquityPropsDao equityPropsDao;
    private final RankingBoardIncomeConfDao rankingBoardIncomeConfDao;
    private final RankingBoardRewardsConfDao rankingBoardRewardsConfDao;
    private final UserRankingBoardDetailsService userRankingBoardDetailsService;
    private final RankingBoardMarketValueAccountDao marketValueAccountDao;
    private final UserInfoDao userInfoDao;
    private final FilterIncomeListDao filterIncomeListDao;
    @Override
    public void addAdminRankingBoard(RankingBoardConf rankingBoardConf) {
        //校验时间
        Assert.isTrue(rankingBoardConf.getBeginTime().before(rankingBoardConf.getEndTime()), ()->  new GlobalRunTimeException("开始时间必须小于结束时间"));
        rankingBoardConf.getBeginTime().setHours(0);
        rankingBoardConf.getBeginTime().setMinutes(0);
        rankingBoardConf.getBeginTime().setSeconds(0);
        rankingBoardConf.setBeginTime(rankingBoardConf.getBeginTime());


        rankingBoardConf.getEndTime().setHours(23);
        rankingBoardConf.getEndTime().setMinutes(59);
        rankingBoardConf.getEndTime().setSeconds(59);
        rankingBoardConf.setEndTime(rankingBoardConf.getEndTime());


        switch (rankingBoardConf.getType()){
            case POSITION_RANKING:
                extracted(rankingBoardConf,RankingBoardTypeEnum.POSITION_RANKING);
                break;
            case IP_MALL_TRADING:
                RankingBoardConf ipMallRankingBoard = rankingBoardConfDao.getLastOneByCollectionIdAndIsEnableAndType(RankingBoardTypeEnum.IP_MALL_TRADING);
                if(ObjectUtil.isNotNull(ipMallRankingBoard)){
                    Assert.isTrue(ipMallRankingBoard.getEndTime().before(rankingBoardConf.getBeginTime()), ()->  new GlobalRunTimeException("开始时间必须大于上一期结束时间"));
                }
                rankingBoardConf.insert();
                break;
            case NEW_POSITION_RANKING:
                extracted(rankingBoardConf,RankingBoardTypeEnum.NEW_POSITION_RANKING);
                break;
            default:
                throw new GlobalRunTimeException("排行榜类型错误");
        }
    }
    private void extracted(RankingBoardConf rankingBoardConf,RankingBoardTypeEnum rankingBoardTypeEnum) {
        Long linkCollectionId = rankingBoardConf.getLinkCollectionId();
        //关联的藏品 同一时间段内同一个藏品只能有一个
        Assert.isTrue((ObjectUtil.isNull(linkCollectionId) || linkCollectionId.intValue() > 0), ()->  new GlobalRunTimeException("持仓排行榜必须关联藏品"));

        //校验关联藏品
        DigitalCollection collection = digitalCollectionDao.getById(linkCollectionId);
        Assert.notNull(collection, ()->  new GlobalRunTimeException("关联藏品不存在"));

        //设置关联藏品信息
        rankingBoardConf.setLinkCollectionId(linkCollectionId);
        rankingBoardConf.setLinkColectionName(collection.getFirstTitle());

        //校验历史记录与新记录是否重合
        RankingBoardConf rankingBoard = rankingBoardConfDao.getLastOneByCollectionIdAndIsEnable(linkCollectionId,rankingBoardTypeEnum);
        if(ObjectUtil.isNotNull(rankingBoard)){
            Assert.isTrue(rankingBoard.getEndTime().before(rankingBoardConf.getBeginTime()), ()->  new GlobalRunTimeException("开始时间必须大于上一期结束时间"));
        }
        rankingBoardConf.insert();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addAdminRankingBoardRewards(Long id, List<AddRewardsSectionVO> rewardsSectionList) {
        RankingBoardConf rankingBoardConf = rankingBoardConfDao.getById(id);
        Assert.notNull(rankingBoardConf, ()->  new GlobalRunTimeException("排行榜不存在"));

        Assert.isTrue(rewardsSectionList.size()>0, ()->  new GlobalRunTimeException("奖励区间不能为空"));
        //校验区间
        for (int i = 0; i < rewardsSectionList.size(); i++) {
            Integer beginSection = rewardsSectionList.get(i).getBeginSection();
            Integer endSection = rewardsSectionList.get(i).getEndSection();
            Assert.isTrue(beginSection < endSection, ()->  new GlobalRunTimeException("开始区间必须大于结束区间"));

            if( i<rewardsSectionList.size()-1){
                Integer nextEndSection = rewardsSectionList.get(i).getEndSection();
                Assert.isTrue(beginSection < nextEndSection, ()->  new GlobalRunTimeException("开始区间必须小于结束区间"));
            }

            log.info("结果:{}",rewardsSectionList.get(i) != rewardsSectionList.get(rewardsSectionList.size()-1));
            if(rewardsSectionList.get(i) != rewardsSectionList.get(rewardsSectionList.size()-1)){
                Integer lastEndSection = rewardsSectionList.get(i+1).getEndSection();
                Assert.isTrue(lastEndSection <= rankingBoardConf.getListNumber(), ()->  new GlobalRunTimeException("奖励区间不能超过榜单人数"));
            }


            List<AddRewardsDetailsVO> rewardsList = rewardsSectionList.get(i).getRewardsList();
            for (AddRewardsDetailsVO addRewardsDetailsVO : rewardsList) {
                Assert.isTrue(addRewardsDetailsVO.getLinkCount().compareTo(BigDecimal.ZERO) == 1, ()->  new GlobalRunTimeException("奖励数量必须大于0"));

                if(addRewardsDetailsVO.getLinkType() == RankingBoardRewardsTypeEnum.PROPS){
                    EquityProps equityProps = equityPropsDao.getById(addRewardsDetailsVO.getLinkId());
                    Assert.notNull(equityProps, ()->  new GlobalRunTimeException("关联权益道具不存在"));
                }

                //初始化每个排名的奖励
                for (int j = beginSection+1; j <= endSection; j++) {
                    RankingBoardRewardsConf rankingBoardRewardsConf = new RankingBoardRewardsConf();
                    rankingBoardRewardsConf.setRankingBoardConfId(rankingBoardConf.getId());
                    rankingBoardRewardsConf.setRanking(j);
                    rankingBoardRewardsConf.setBeginSection(beginSection);
                    rankingBoardRewardsConf.setEndSection(endSection);
                    rankingBoardRewardsConf.setLinkType(addRewardsDetailsVO.getLinkType());
                    rankingBoardRewardsConf.setLinkImage(addRewardsDetailsVO.getLinkImage());
                    rankingBoardRewardsConf.setLinkName(addRewardsDetailsVO.getLinkName());
                    rankingBoardRewardsConf.setLinkId(addRewardsDetailsVO.getLinkId());
                    rankingBoardRewardsConf.setLinkCount(addRewardsDetailsVO.getLinkCount());
                    rankingBoardRewardsConf.insert();
                }
            }
        }
    }

    @Override
    public Page<PageRankingBoardListByIncomeTypeVO> getPageRankingBoardListByIncomeType(ExpenditureRecordTypeEnum expenditureRecordTypeEnum, Integer pageNo, Integer pageSize) {
        switch (expenditureRecordTypeEnum) {
            case RANKING_BOARD_INCOME:
                return rankingBoardConfDao.getPageRankingBoardListByIncomeType(RankingBoardTypeEnum.POSITION_RANKING, pageNo, pageSize);
            case IP_MALL_RANKING_BOARD_INCOME:
                return rankingBoardConfDao.getPageRankingBoardListByIncomeType(RankingBoardTypeEnum.IP_MALL_TRADING, pageNo, pageSize);
            default:
                throw new GlobalRunTimeException("收益类型错误");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addRankingBoardIncome(Long id, List<AdminRankingBoardIncomeDetailsVO> incomeList) {
        RankingBoardConf rankingBoardConf = rankingBoardConfDao.getById(id);
        Assert.notNull(rankingBoardConf, ()->  new GlobalRunTimeException("排行榜不存在"));
        Assert.isFalse(rankingBoardConf.getIsEnable(), ()->  new GlobalRunTimeException("排行榜已启用不能关联收益"));

        Assert.isTrue(incomeList.size()>0, ()->  new GlobalRunTimeException("收益区间不能为空"));

        for (int i = 0; i < incomeList.size(); i++) {
            Integer beginSection = incomeList.get(i).getBeginSection();
            Integer endSection = incomeList.get(i).getEndSection();
            Assert.isTrue(beginSection < endSection, ()->  new GlobalRunTimeException("开始区间必须大于结束区间"));

            if(i<incomeList.size()-1){
                Integer nextEndSection = incomeList.get(i).getEndSection();
                Assert.isTrue(beginSection < nextEndSection, ()->  new GlobalRunTimeException("开始区间必须小于上一条结束区间"));
            }


            if(incomeList.get(i) != incomeList.get(incomeList.size()-1)){
                Integer nextEndSection = incomeList.get(i+1).getEndSection();
                Assert.isTrue(nextEndSection <= rankingBoardConf.getListNumber(), ()->  new GlobalRunTimeException("区间不能超过榜单人数"));
            }


            AdminRankingBoardIncomeDetailsVO adminRankingBoardIncomeDetailsVO = incomeList.get(i);

            if(rankingBoardConf.getType() == RankingBoardTypeEnum.POSITION_RANKING && adminRankingBoardIncomeDetailsVO.getExpenditureRecordTypeEnum() == ExpenditureRecordTypeEnum.IP_MALL_RANKING_BOARD_INCOME){
                throw new GlobalRunTimeException("持仓排行榜不能配置IP商城交易激励");
            }

            Assert.isTrue(adminRankingBoardIncomeDetailsVO.getIncomeProportion().compareTo(BigDecimal.ZERO) == 1, ()->  new GlobalRunTimeException("收益比例必须大于0"));
            for (int j = adminRankingBoardIncomeDetailsVO.getBeginSection() + 1; j <= adminRankingBoardIncomeDetailsVO.getEndSection(); j++) {
                RankingBoardIncomeConf inserIncome = new RankingBoardIncomeConf();
                inserIncome.setRankingBoardConfId(rankingBoardConf.getId());
                inserIncome.setType(rankingBoardConf.getType());
                inserIncome.setRanking(j);
                inserIncome.setIncomeName(adminRankingBoardIncomeDetailsVO.getIncomeName());
                inserIncome.setIncomeProportion(adminRankingBoardIncomeDetailsVO.getIncomeProportion().movePointLeft(2));
                inserIncome.setBeginSection(beginSection);
                inserIncome.setEndSection(endSection);
                inserIncome.setExpenditureRecordType(adminRankingBoardIncomeDetailsVO.getExpenditureRecordTypeEnum());

                if(rankingBoardConf.getType() == RankingBoardTypeEnum.POSITION_RANKING) {
                    inserIncome.setLinkConllectionId(rankingBoardConf.getLinkCollectionId());
                    inserIncome.setLinkConllectionName(rankingBoardConf.getLinkColectionName());
                }
                inserIncome.insert();
            }

        }

    }

    @Override
    public Page<PageRankingBoardListByTypeVO> getPageRankingBoardListByType(RankingBoardTypeEnum type, Integer pageNo, Integer pageSize,String name,String beginTime,String endTime,String linkCollectonName,Integer isEnable) {
        return rankingBoardConfDao.getPageRankingBoardListByType(type, pageNo, pageSize,name,beginTime,endTime,linkCollectonName,isEnable);
    }

    @Override
    public void updateRankingBoardIsEnable(Long id, Boolean isEnable) {
        RankingBoardConf rankingBoardConf = rankingBoardConfDao.getById(id);
        Assert.notNull(rankingBoardConf, ()->  new GlobalRunTimeException("排行榜不存在"));
        Assert.isTrue(rankingBoardConf.getIsEnable() != isEnable, ()->  new GlobalRunTimeException("排行榜状态不能重复修改"));
        Assert.isTrue(rankingBoardConfDao.updateIsEnableById(id, isEnable), ()->  new GlobalRunTimeException("修改失败"));
    }

    @Override
    public void updateRankingBoardIsOpenRewards(Long id, Boolean isOpenRewards) {
        RankingBoardConf rankingBoardConf = rankingBoardConfDao.getById(id);
        Assert.notNull(rankingBoardConf, ()->  new GlobalRunTimeException("排行榜不存在"));
        Assert.isTrue(rankingBoardConf.getIsOpenRewards() != isOpenRewards, ()->  new GlobalRunTimeException("排行榜状态不能重复修改"));

        Integer count = rankingBoardRewardsConfDao.getCountByRankingBoardConfId(rankingBoardConf.getId());
        Assert.isTrue(count > 0, ()->  new GlobalRunTimeException("排行榜奖励配置不能为空"));
        Assert.isTrue(rankingBoardConfDao.updateIsOpenRewardsById(id, isOpenRewards), ()->  new GlobalRunTimeException("修改失败"));
    }

    @Override
    public void updateRankingBoardSort(Long id, Integer sort) {
        RankingBoardConf rankingBoardConf = rankingBoardConfDao.getById(id);
        Assert.notNull(rankingBoardConf, ()->  new GlobalRunTimeException("排行榜不存在"));
        Assert.isTrue(rankingBoardConfDao.updateSortById(id, sort), ()->  new GlobalRunTimeException("修改失败"));
    }

    @Override
    public void updateRankingBoardMinimumQuantity(Long id, Integer minimumQuantity, String ruleSpecification) {
        RankingBoardConf rankingBoardConf = rankingBoardConfDao.getById(id);
        Assert.notNull(rankingBoardConf, ()->  new GlobalRunTimeException("排行榜不存在"));
        Assert.isTrue(!rankingBoardConf.getMinimumQuantity().equals(minimumQuantity) || !rankingBoardConf.getRuleSpecification().equals(ruleSpecification), ()->  new GlobalRunTimeException("排行榜状态不能重复修改"));
        Assert.isTrue(minimumQuantity > 0, ()->  new GlobalRunTimeException("最低入榜条件必须大于0"));
        Assert.isFalse(rankingBoardConf.getIsEnable(), ()->  new GlobalRunTimeException("排行榜启用状态不能修改"));
        Assert.isTrue(rankingBoardConfDao.updateRankingBoardMinimumQuantity(id, minimumQuantity,ruleSpecification), ()->  new GlobalRunTimeException("修改失败"));
    }
    @Override
    public List<GetRankingBoardDetailsVO> getRankingBoardDetails(Long id, String userTel) {
        RankingBoardConf rankingBoardConf = rankingBoardConfDao.getById(id);

        if(rankingBoardConf.getIsSettlement()){ //已经结算完毕了
            return userRankingBoardDetailsService.getHistoryDetailsByIdAndUserTel(id, userTel);
        }else{
            int hours = DateTime.now().getHours();
            if(hours  % 2 == 0){//偶数表
                List<GetRankingBoardDetailsVO> evenNumberList = userRankingBoardDetailsService.getEvenNumberDetailsByIdAndUserTel(id, userTel);
                if(evenNumberList.size() == 0){//如果偶数表没有数据 则返回奇数表数据
                    return userRankingBoardDetailsService.getOddNumberDetailsByIdAndUserTel(id, userTel);
                }
                return evenNumberList;
            }else{//奇数表
                List<GetRankingBoardDetailsVO> oddNumberList = userRankingBoardDetailsService.getOddNumberDetailsByIdAndUserTel(id, userTel);
                if(oddNumberList.size() ==0){ //如果奇数表没有数据 则返回偶数表数据
                    return userRankingBoardDetailsService.getEvenNumberDetailsByIdAndUserTel(id, userTel);
                }
                return oddNumberList;
            }
        }

    }

    @Override
    public void delRankingBoard(Long id) {
        RankingBoardConf rankingBoardConf = rankingBoardConfDao.getById(id);
        Assert.notNull(rankingBoardConf, ()->  new GlobalRunTimeException("排行榜不存在"));
        Assert.isFalse(rankingBoardConf.getIsEnable(), ()->  new GlobalRunTimeException("排行榜启用状态不能删除"));
        Assert.isTrue(rankingBoardConfDao.delRankingBoard(id), ()->  new GlobalRunTimeException("删除失败"));
    }

    @Override
    public List<AdminRankingBoardRewardsDetailsVO> getRankingBoardRewardsDetails(Long id) {
        return rankingBoardRewardsConfDao.getRankingBoardRewardsDetailsById(id);
    }

    @Override
    public List<AdminRankingBoardIncomeDetailsVO> getRankingBoardIncomeDetails(Long rankingBoardConfId) {
        return rankingBoardIncomeConfDao.getRankingBoardIncomeDetails(rankingBoardConfId);
    }

    @Override
    public void delRankingBoardIncomeDetails(Long rankingBoardConfId, Integer beginSection, Integer endSection) {
        RankingBoardConf rankingBoardConf = rankingBoardConfDao.getById(rankingBoardConfId);
        Assert.notNull(rankingBoardConf, ()->  new GlobalRunTimeException("排行榜不存在"));

        Integer count = rankingBoardIncomeConfDao.getCountByRankingBoardConfIdAndBeginSectionAndEndSection(rankingBoardConfId, beginSection, endSection);
        Assert.isTrue(count > 0, ()->  new GlobalRunTimeException("删除失败,该区间不存在"));

        Assert.isTrue(rankingBoardIncomeConfDao.delRankingBoardIncomeDetails(rankingBoardConfId, beginSection, endSection), ()->  new GlobalRunTimeException("删除失败"));
    }

    @Override
    public void addMarketValueAccount(Long rankingBoardConfId, String userTel) {
        RankingBoardConf rankingBoardConf = rankingBoardConfDao.getById(rankingBoardConfId);
        Assert.notNull(rankingBoardConf, ()->  new GlobalRunTimeException("排行榜不存在"));

        Integer count = marketValueAccountDao.getCountByRankingBoardConfIdAndMarketValueAccount(rankingBoardConfId,userTel);
        Assert.isTrue(count == 0, ()->  new GlobalRunTimeException("该用户已经关联此排行版"));

        UserInfo user = userInfoDao.getOneByUserTel(userTel);
        Assert.notNull(user, ()->  new GlobalRunTimeException("用户不存在"));

        FilterIncomeList filterIncomeList = filterIncomeListDao.getIsTeamIncomeByUserId(user.getId());
        Assert.notNull(filterIncomeList , ()->  new GlobalRunTimeException("市值账号不存在!"));

        RankingBoardMarketValueAccount marketValueAccount = new RankingBoardMarketValueAccount();
        marketValueAccount.setRankingBoardConfId(rankingBoardConfId);
        marketValueAccount.setMarketValueAccount(userTel);


        marketValueAccount.setMarketValueUserId(user.getId());
        marketValueAccount.insert();
    }

    @Override
    public void updateRankingBoardDetailsStatusByUser(Long id, Integer ranking, RankingBoardIncomeAndRewardsStatusEnum status) {
        RankingBoardConf rankingBoardConf = rankingBoardConfDao.getById(id);
        Assert.notNull(rankingBoardConf, ()->  new GlobalRunTimeException("排行榜不存在"));
        Assert.isTrue(rankingBoardConf.getIsEnable(), ()->  new GlobalRunTimeException("排行榜未启用"));
        Assert.isTrue(rankingBoardConf.getIsSettlement(), ()->  new GlobalRunTimeException("排行榜未结算"));
        Assert.isTrue(rankingBoardConf.getIsOpenRewards(), ()->  new GlobalRunTimeException("排行榜未开启奖励"));

        RankingBoardHistoryDetails rankingBoardHistoryDetails = userRankingBoardDetailsService.getOneByRankingBoardConfIdAndRanking(id, ranking);
        Assert.notNull(rankingBoardHistoryDetails, ()->  new GlobalRunTimeException("排行榜详情不存在"));

        Assert.isFalse(rankingBoardHistoryDetails.getStatus() == RankingBoardIncomeAndRewardsStatusEnum.ISSUED, ()->  new GlobalRunTimeException("已发放的状态,不能在修改!"));
        Assert.isFalse(status == RankingBoardIncomeAndRewardsStatusEnum.ISSUED, ()->  new GlobalRunTimeException("不能直接修改到已发放状态!"));

        Assert.isTrue(userRankingBoardDetailsService.updateRankingBoardDetailsStatusByRankingBoardConfIdAndRanking(id, ranking, status), ()->  new GlobalRunTimeException("修改失败"));
    }


}